﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;

//// 0~N 个参数
//template<class ...Args>
//void Print(Args&&... args)
//{
//	// sizeof... 运算符与 sizeof 运算符不同
//	// 可以计算参数包里有几个参数
//	cout << sizeof...(args) << endl;
//}
//
//int main()
//{
//	double x = 2.2;
//	Print(); // 包⾥有0个参数 
//	Print(1); // 包⾥有1个参数 
//	Print(1, string("xxxxx")); // 包⾥有2个参数 
//	Print(1.1, string("xxxxx"), x); // 包⾥有3个参数 
//	return 0;
//}
//
//// 原理1：编译本质这⾥会结合引⽤折叠规则实例化出以下四个函数 
//
//void Print();
//
//void Print(int&& arg1);
//
//void Print(int&& arg1, string&& arg2);
//
//void Print(double&& arg1, string&& arg2, double& arg3);
//
//// 原理2：更本质去看没有可变参数模板，我们实现出这样的多个函数模板才能⽀持 
//// 这⾥的功能，有了可变参数模板，我们进⼀步被解放，他是类型泛化基础 
//// 上叠加数量变化，让我们泛型编程更灵活。 
//void Print();
//
//template <class T1>
//void Print(T1&& arg1);
//
//template <class T1, class T2>
//void Print(T1&& arg1, T2&& arg2);
//
//template <class T1, class T2, class T3>
//void Print(T1&& arg1, T2&& arg2, T3&& arg3);
//
//// ...

//template<class ...Args>
//void Print(Args&&... args)
//{
//	// 不支持
//	for (size_t i = 0; i < sizeof...(args); i++)
//	{
//		// 不支持
//		cout << args[i] << " ";
//	}
//	cout << endl;
//}


// 包扩展（解析出参数包的内容）

//// 0个参数直接调用 ↓
//void ShowList()
//{
//	// 编译器时递归的终⽌条件，参数包是0个时，直接匹配这个函数 
//	cout << endl;
//}
//
//template <class T, class ...Args>
//void ShowList(T&& x, Args&&... args)
//{
//	cout << x << " ";
//	// args是N个参数的参数包 
//	// 调⽤ShowList，参数包的第⼀个传给x，剩下N-1传给第⼆个参数包 
//	ShowList(args...);
//}
//
//// 编译时递归推导解析参数 
//template <class ...Args>
//void Print(Args&&... args)
//{
//	// 定义的时候：...在前
//	// 使用的时候：...在后
//	ShowList(args...);
//}
//
//int main()
//{
//	Print();
//	Print(1);
//	Print(1, string("xxxxx"));
//	Print(1, string("xxxxx"), 2.2);
//	return 0;
//}

//template <class T>
//const T& GetArg(const T& x)
//{
//	cout << x << " ";
//	return x;
//}
//
//template <class ...Args>
//void Arguments(Args... args)
//{}
//
//template <class ...Args>
//void Print(Args... args)
//{
//	// 注意GetArg必须返回或者到的对象，这样才能组成参数包给Arguments 
//	Arguments(GetArg(args)...);
//	// GetArg(args)... 对每个参数调用一遍GetArg函数
//}

//template<class ...Args>
//void print(Args&&... args)
//{
//	// 折叠表达式（C++17才支持）
//	(cout << ... << args) << endl;
//}
//
//int main()
//{
//	print(1.1, 2, "xxxx");
//	return 0;
//}



//// emplace系列兼容push系列和insert的功能
//// 部分场景下emplace可以直接构造，push和insert是构造+移动构造或者构造+拷贝构造
//// 所以emplace综合而言刚好用更强大，推荐用emplace系列替代push和insert系列
//
//int main()
//{
//	list<pair<string, int>> lt1;
//	// 构造 + 移动构造
//	lt1.push_back({ "苹果", 1 });
//
//	lt1.emplace_back("苹果", 1);
//	
//	// lt1.emplace_back({ "苹果", 1 }); // 错误
//	return 0;
//}

//template<class ...Args>
//void emplace_back(Args&&... args)
//{
//	// 参数包的完美转发需要写...
//	insert(end(), forward<Args>(args)...);
//}
//
//template <class... Args>
//iterator insert(iterator pos, Args&&... args)
//{
//	Node* cur = pos._node;
//	// 参数包的完美转发需要写...
//	Node* newnode = new Node(std::forward<Args>(args)...);
//	Node* prev = cur->_prev;
//	// prev newnode cur
//	prev->_next = newnode;
//	newnode->_prev = prev;
//	newnode->_next = cur;
//	cur->_prev = newnode;
//	return iterator(newnode);
//}
//
//template <class... Args>
//ListNode(Args&&... args)
//	: _next(nullptr)
//	, _prev(nullptr)
//	// 参数包的完美转发需要写...
//	, _data(std::forward<Args>(args)...)
//{}

// lambda

//int main()
//{
//	// 代表一个匿名函数对象
//	auto add1 = [](int x, int y)->int {return x + y; };
//	cout << add1(1, 2) << endl;
//	 // 1、捕捉为空也不能省略 
//	 // 2、参数为空可以省略 
//	 // 3、返回值可以省略，可以通过返回对象⾃动推导 
//	 // 4、函数体不能省略 
//	auto func1 = []
//		{
//			cout << "zgx" << endl;
//			return 0;
//		};
//	func1();
//
//	int a = 0, b = 1;
//	auto swap1 = [](int& x, int& y)
//		{
//			int tmp = x;
//			x = y;
//			y = tmp;
//		};
//	swap1(a, b);
//	cout << a << ":" << b << endl;
//
//
//	return 0;
//}

struct Goods
{
	string _name; // 名字 
	double _price; // 价格 
	int _evaluate; // 评价 
	// ...
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};

struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price < gr._price;
	}
};

struct ComparePriceGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price > gr._price;
	}
};

int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "⾹蕉", 3, 4 }, { "橙⼦", 2.2, 3}, { "菠萝", 1.5, 4 } };

	// 类似这样的场景，我们实现仿函数对象或者函数指针⽀持商品中 
	// 不同项的⽐较，相对还是⽐较⿇烦的，那么这⾥lambda就很好⽤了 

	sort(v.begin(), v.end(), ComparePriceLess());
	sort(v.begin(), v.end(), ComparePriceGreater());

	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price < g2._price; });

	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._price > g2._price; });

	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._evaluate < g2._evaluate; });

	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {return g1._evaluate > g2._evaluate; });

	return 0;
}